using System;
using System.Collections.Generic;

namespace OracleInternal.SqlAndPlsqlParser
{
	internal class ParserGrammarDefinition
	{
		public string[] m_vAllSymbols;

		public IntSortedMap<string> m_vSymbolIndexes;

		public IntSortedMap<string> m_vQuotedSymbolIndexes;

		public ParserRuleTuple[] m_vRules;

		public ParserRuleTuple[] m_vBaseSortedRules;

		public int[] m_vSortedRulesIndexes;

		public int[] m_vSymbolsFlags;

		public ParserGrammarDefinition(Set<RuleTuple> rules)
		{
			if (rules == null)
			{
				throw new ArgumentNullException("The set of rules can't be null!");
			}
			InitializeSymbols(rules);
			InitializeRulesInformation(rules);
			InitializeSpecialWords();
		}

		protected void InitializeSymbols(Set<RuleTuple> rules)
		{
			Set<string> set = new Set<string>();
			int num;
			foreach (RuleTuple rule in rules)
			{
				string[] vRhs = rule.m_vRhs;
				num = vRhs.Length;
				string vHead = rule.m_vHead;
				if (vHead == null || num == 0 || vRhs[0] == null || (num > 1 && vRhs[1] == null))
				{
					throw new ParserException(ParserExceptionType.Grammar, ParserExceptionError.RuleTupleNullSymbols);
				}
				set.Add(vHead);
				string[] array = vRhs;
				foreach (string item in array)
				{
					set.Add(item);
				}
			}
			num = set.Count;
			m_vAllSymbols = set.ToArray();
			m_vSymbolsFlags = new int[num];
			for (int j = 0; j < num; j++)
			{
				m_vSymbolsFlags[j] = 0;
			}
			Array.Sort(m_vAllSymbols, (IComparer<string>?)StringComparer.Ordinal);
			m_vSymbolIndexes = new IntSortedMap<string>(StringComparer.Ordinal);
			m_vQuotedSymbolIndexes = new IntSortedMap<string>(StringComparer.InvariantCultureIgnoreCase);
			for (int k = 0; k < num; k++)
			{
				string text = m_vAllSymbols[k];
				m_vSymbolIndexes[text] = k;
				if (text[0] == '\'' && text[text.Length - 1] == '\'')
				{
					m_vQuotedSymbolIndexes[text.Substring(1, text.Length - 2)] = k;
				}
			}
		}

		protected void InitializeRulesInformation(Set<RuleTuple> rules)
		{
			int num = 0;
			m_vRules = new ParserRuleTuple[rules.Count];
			m_vSortedRulesIndexes = new int[rules.Count];
			foreach (RuleTuple rule in rules)
			{
				string[] vRhs = rule.m_vRhs;
				int num2 = m_vSymbolIndexes[rule.m_vHead];
				m_vSymbolsFlags[num2] |= 2;
				int[] array = new int[vRhs.Length];
				for (int i = 0; i < vRhs.Length; i++)
				{
					int num3 = (array[i] = m_vSymbolIndexes[vRhs[i]]);
					if (num3 != num2)
					{
						m_vSymbolsFlags[num3] |= 4;
					}
				}
				m_vSortedRulesIndexes[num] = num;
				m_vRules[num++] = new ParserRuleTuple(num2, array, this);
			}
			Array.Sort(m_vRules, ParserRuleTupleBaseComparer.s_vInstance);
			m_vBaseSortedRules = (ParserRuleTuple[])m_vRules.Clone();
			for (int i = 0; i < m_vAllSymbols.Length; i++)
			{
				if ((m_vSymbolsFlags[i] & 6) == 4)
				{
					m_vSymbolsFlags[i] |= 1;
				}
			}
		}

		protected virtual void InitializeSpecialWords()
		{
		}

		public bool IsTerminal(int idx)
		{
			return (m_vSymbolsFlags[idx] & 1) != 0;
		}

		internal int GetRuleIndex(string head, string[] rhs)
		{
			int h = m_vSymbolIndexes[head];
			int[] array = new int[rhs.Length];
			for (int i = 0; i < rhs.Length; i++)
			{
				int num = (array[i] = m_vSymbolIndexes[rhs[i]]);
			}
			return Array.BinarySearch(m_vBaseSortedRules, new ParserRuleTuple(h, array, this), ParserRuleTupleBaseComparer.s_vInstance);
		}
	}
}
